package com.github.common.extend.demo.util.excel.dynamic;

import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 带自定义标题的excel写入拦截
 * @author wangjj7
 * @date 2023/9/7
 * @description
 */
public class DynamicTitleWriteHandler<K> implements SheetWriteHandler ,RowWriteHandler {

    /**
     * 自定义标签元数据
     */
    private final List<DynamicTitleDefine<K>> dynamicTitleDefines;

    /**
     * 由于拦截器内部没有保存迭代写入时每行映射的数据，这里只能通过外部传进来了
     */
    private final Iterator<? extends DynamicTitleRow<K>> rowIterator;

    /**
     * 列下标与自定义标签元数据映射
     * key: {@link DynamicTitleDefine#getName()}
     */
    private Map<Integer ,DynamicTitleDefine<K>> dynamicTitleIndex2DefineMap;

    /**
     * 当前行对应的数据
     */
    private DynamicTitleRow currentRow;

    public DynamicTitleWriteHandler(List<DynamicTitleDefine<K>> dynamicTitleDefines,
                                    Iterator<? extends DynamicTitleRow<K>> rowIterator)
    {
        Objects.requireNonNull(rowIterator);

        this.dynamicTitleDefines = dynamicTitleDefines == null ? Collections.EMPTY_LIST :
                dynamicTitleDefines.stream()
                        .sorted(Comparator.comparing(DynamicTitleDefine::getOrder))
                        .collect(Collectors.toList());
        this.rowIterator = rowIterator;
    }

    private void parseDynamicTitleIndexMap(SheetWriteHandlerContext context)
    {
        if (dynamicTitleIndex2DefineMap == null){
            dynamicTitleIndex2DefineMap = new HashMap<>();

            if (CollectionUtils.isEmpty(dynamicTitleDefines)){
                return;
            }

            int dynamicTitleColumnIndex = context.getWriteSheetHolder()
                    .getExcelWriteHeadProperty()
                    .getHeadMap()
                    .keySet()
                    .stream()
                    .mapToInt(Integer::intValue)
                    .max()
                    .orElse(-1) + 1;

            for (DynamicTitleDefine dynamicTitleDefine : dynamicTitleDefines) {
                dynamicTitleIndex2DefineMap.put(dynamicTitleColumnIndex++ ,dynamicTitleDefine);
            }
        }
    }

    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context)
    {
        SheetWriteHandler.super.afterSheetCreate(context);
        parseDynamicTitleIndexMap(context);
    }

    @Override
    public void afterRowDispose(RowWriteHandlerContext context) {
        RowWriteHandler.super.afterRowDispose(context);
        if (context.getHead()){
            setDynamicTitleHeadCell(context);
        }else {
            setDynamicTitleDataCell(context);
        }
    }

    private void setDynamicTitleHeadCell(RowWriteHandlerContext context)
    {
        if (!context.getHead() || MapUtils.isEmpty(dynamicTitleIndex2DefineMap)){
            return;
        }

        Row row = context.getRow();
        for (Map.Entry<Integer, DynamicTitleDefine<K>> entry : dynamicTitleIndex2DefineMap.entrySet())
        {
            Cell cell = row.createCell(entry.getKey());
            DynamicTitleDefine dynamicTitleDefine = entry.getValue();
            cell.setCellValue(dynamicTitleDefine.getName());

            WriteCellStyle writeCellStyle = new WriteCellStyle();
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cell.setCellStyle(context.getWriteWorkbookHolder().createCellStyle(writeCellStyle ,cell.getCellStyle()));
        }
    }

    private void setDynamicTitleDataCell(RowWriteHandlerContext context)
    {
        DynamicTitleRow dynamicTitleRow = rowIterator.next();
        if (MapUtils.isEmpty(dynamicTitleIndex2DefineMap) || dynamicTitleRow == null){
            return;
        }

        List<DynamicTitleCell<K>> dynamicTitleCells = dynamicTitleRow.getDynamicTitleCells();
        if (CollectionUtils.isEmpty(dynamicTitleCells)) {
            return;
        }

        Row row = context.getRow();
        Map<K, DynamicTitleCell<K>> dynamicTitleCellDataMap = dynamicTitleCells.stream()
                .collect(Collectors.toMap(DynamicTitleCell::getKey, Function.identity() ,(v0 ,v1) -> v0));

        for (Map.Entry<Integer, DynamicTitleDefine<K>> entry : dynamicTitleIndex2DefineMap.entrySet()) {
            Integer dynamicTitleIndex = entry.getKey();
            DynamicTitleDefine<K> dynamicTitleDefine = entry.getValue();
            Cell cell = row.createCell(dynamicTitleIndex);
            DynamicTitleCell<K> dynamicTitleCell = dynamicTitleCellDataMap.get(dynamicTitleDefine.getKey());
            if (dynamicTitleCell != null && StringUtils.isNotBlank(dynamicTitleCell.getValue())) {
                cell.setCellValue(dynamicTitleCell.getValue());
            }
        }
    }

}
